package com.example.demo.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.annotation.CacheInRedis;
import com.example.demo.entity.base.ResponseEntity;
import com.example.demo.util.EmptyUtil;
import com.example.demo.util.RedisUtil;
import com.example.demo.util.ResponseFactory;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @title:	CacheRedisAspect
 * @author:	许子文
 * @date:	2021年4月13日 
 * @descirption: redis缓存切面
 *
 */
@Slf4j
@Aspect
@Component
public class CacheRedisAspect {
	
	@Autowired
	private RedisUtil redisUtil;
	
	@Pointcut("@annotation(com.example.demo.annotation.CacheInRedis)")
	public void addAdvice() {
		
	}
	
	@Around("addAdvice()")
	public Object intercepter(ProceedingJoinPoint pjp) {
		Object result = null;
		
		Class<?> aClass = pjp.getTarget().getClass();//获得所在切点的该类的class对象
		
		String methodName = pjp.getSignature().getName();//获得该切点所在的方法的名称
		
		Class<?>[] parameterTypes = ((MethodSignature)pjp.getSignature()).getParameterTypes();//拿到方法对应的参数类型
		
		String redisKey = null;
		long cacheTime;
		boolean useCache;
		
		try {
			Method method = aClass.getMethod(methodName, parameterTypes);//获取该方法对象
			
			CacheInRedis annotion = method.getAnnotation(CacheInRedis.class);
			
			redisKey = annotion.redisKey();
			
			cacheTime = annotion.cacheTime();
			
			useCache = annotion.useCache();
			
		} catch (Exception e) {
			log.error("获取redis缓存切面的值失败",e);
			return ResponseFactory.setFail("获取redis缓存切面的值失败");
		}
		
		if(!useCache||EmptyUtil.isEmpty(redisKey)||0L==cacheTime) {
			log.warn("缓存被禁用或未设置redis的key值或超时时间为0,不走缓存,继续执行原方法");
			try {
				result = pjp.proceed();
			} catch (Throwable e) {
				log.error("走原来的方法产生错误,[nocache]",e);
				return ResponseFactory.setFail("走原来的方法产生错误,[nocache]");
			}
			return result;
		}
		
		String cacheDataStr = null; 
		
		try {
			cacheDataStr = redisUtil.getValue(redisKey);
		} catch (Exception e) {
			log.error("从redis中获取缓存数据失败,[cache]",e);
			return ResponseFactory.setFail("从redis中获取缓存数据失败,[cache]");
		}
		
		result = JSONObject.parseObject(cacheDataStr);
		
		return result;
	}
}
